<?php





namespace App\Http\Controller;


use App\Model\Entity\DeviceCmd;
use App\Model\Entity\SensorType;
use App\HTTP\Utils\DianxingApi;
use App\Model\Entity\ProductSensorType;
use App\Model\Entity\User;
use App\Model\Entity\LogIn;
use App\Model\Entity\Product;
use App\Model\Entity\Device;
use ReflectionException;
use Swoft\Bean\Exception\ContainerException;
use Swoft\Db\Exception\DbException;
use Swoft\Http\Server\Annotation\Mapping\Middleware;
use Swoole\Coroutine\Http\Client;
use Swoft\Exception\SwoftException;
use Swoft\Http\Message\Response;
use Swoft\Http\Server\Annotation\Mapping\Controller;
use Swoft\Http\Server\Annotation\Mapping\RequestMapping;
use Swoft\Log\Helper\Log;
use Swoft\Bean\Annotation\Mapping\Bean;
use Swoft\Config\Annotation\Mapping\Config;
use Swoole\Exception;
use App\Http\Middleware\AuthMiddleware;
use function Swlib\Http\str;

/**
 * Class HelloController
 * @Controller("/v1/Device")
 * @Middleware(AuthMiddleware::class)
 * @package App\Http\Controller
 */
class DeviceController
{
    /**
     * 查询数据
     * @RequestMapping("/v1/Device/SensorType[/{deviceId}]")
     * @param $deviceId string
     * @return Response
     * @throws SwoftException
     */
    public function Get(string $deviceId): Response
    {
        $request = Context()->getRequest();
        $response = Context()->getResponse();

        $mentod = $request->getMethod();

        $headers = $request->getHeaders();


        if ($mentod == "GET")
            $data = $request->get();
        else {
            Log::error("Error!");
            return $response->withStatus(404);

        }
        if(Context()->get("user") == null)
            return $response->withStatus(500)->withData(["errorMsg"=>"服务去错误"]);

        if($deviceId ==null ||  $deviceId== "")
            return $response->withStatus(400)->withData(["error"=>"1","errorMsg"=>"deviceId错误"]);
        try{
            if(Device::join("user",'device.userid', '=', 'user.userid')->where("deviceId",$deviceId)->count() <= 0)
                return $response->withStatus(400)->withData(["error"=>"2","errorMsg"=>"设备不存在"]);
            $sensor_types =  ProductSensorType::join("device","device.productId","=","product_sensor_type.productId")
                ->where("device.deviceId",$deviceId)->select("product_sensor_type.type_name")->get();
            $aray = array();
            foreach ($sensor_types as $sensor_type)
            {
                $Sensor_db = SensorType::where("type_name",$sensor_type["type_name"]);
                $unit = $Sensor_db->get()[0]["unit"];
                $name = $Sensor_db->get()[0]["describe"];
                array_push($aray,["type_name"=>$sensor_type["type_name"],"Name" => $name,"unit" => $unit]);
            }
            return $response->withData(["user"=>Context()->get("user"),"deviceId"=>$deviceId,"SensorTypes"=>$aray,"time"=>time()]);


        } catch (ReflectionException $e) {
            return $response->withStatus(400)->withData(["error"=>"5","errorMsg"=>$e->getMessage()]);
        } catch (ContainerException $e) {
            return $response->withStatus(400)->withData(["error"=>"5","errorMsg"=>$e->getMessage()]);
        } catch (DbException $e) {
            return $response->withStatus(400)->withData(["error"=>"5","errorMsg"=>$e->getMessage()]);
        }
    }
    /**
     * 查询设备列表
     * @RequestMapping("/v1/Device")
     * @throws Exception
     * @throws SwoftException
     */
    public function Device(): Response
    {
        $request = Context()->getRequest();
        $response = Context()->getResponse();

        $mentod = $request->getMethod();

        $headers = $request->getHeaders();


        if ($mentod == "GET")
            $data = $request->get();
        else {
            Log::error("Error!");
            return $response->withStatus(404);

        }
        if(Context()->get("user") == null)
            return $response->withStatus(500)->withData(["errorMsg"=>"服务去错误"]);

        $pageSize = (string)1;
        $pageNo = null;
        if(isset($data["pageNo"]) && is_numeric($data["pageNo"]) && $data["pageNo"] >0 )
        {
            $pageNo = $data["pageNo"];
            if(isset($data["pageSize"]) && is_numeric($data["pageSize"]) && $data["pageSize"]>0)
                $pageSize = $data["pageSize"];

        }
        try{
            $devices = ["user"=>Context()->get("user")];
            if($pageNo != null) {
                $devices["pageNo"] = (string)$pageNo;
                $devices["pageSize"] = (string)$pageSize;
            }
            $dbRec =  Device::join('user', 'device.userid', '=', 'user.userid')
                ->select('device.deviceId','device.productId','device.model','device.key','device.imei','device.createdDate as time')
                ->where("user.UserName",Context()->get("user"))->orderBy("device.createdDate","desc");
            if($pageNo != null)
            {
                $devices["pageAmount"] = ((int) ($dbRec->count()/$pageSize)  );
                if($dbRec->count()%$pageSize != 0)
                    $devices["pageAmount"] += 1;
                $devices["pageAmount"] = (string)$devices["pageAmount"];
                $devices["devices"] = $dbRec->forPage($pageNo,$pageSize)->get();
            }
            else {
                $devices["devices"] = $dbRec->get();

            }

            $devices["count"] = count($devices["devices"]);
            return $response->withData($devices);

        } catch (ReflectionException $e) {
        return $response->withStatus(400)->withData(["error"=>"5","errorMsg"=>$e->getMessage()]);
        } catch (ContainerException $e) {
            return $response->withStatus(400)->withData(["error"=>"5","errorMsg"=>$e->getMessage()]);
        } catch (DbException $e) {
            return $response->withStatus(400)->withData(["error"=>"5","errorMsg"=>$e->getMessage()]);
        }



    }

    /**
     * @RequestMapping("/v1/delDevice")
     * @throws Exception
     * @throws SwoftException
     * @throws DbException
     */
    public function delDevice(): Response
    {

        $request = Context()->getRequest();
        $response = Context()->getResponse();

        $mentod = $request->getMethod();

        $headers = $request->getHeaders();



        if($mentod == "POST")
            $data = $request->post();
        else {
            Log::error("Error!");
            return $response->withStatus(404);

        }



        if(!isset($data["deviceId"]))
            return $response->withStatus(400)->withData(["error"=>"1","errorMsg"=>"没有设置deviceId"]);


        if(Device::where("deviceId",$data["deviceId"])->get()->count() <= 0)
            return $response->withStatus(400)->withData(["error"=>"2","errorMsg"=>"设备id不存在(".$data["deviceId"].")"]);
        $deviceid = Device::where("deviceId",$data["deviceId"])->get()[0]["Nb_deviceId"];
        if($deviceid == "")
            return $response->withStatus(400)->withData(["error"=>"3","errorMsg"=>"设备id没有电信平台设备信息(".$data["deviceId"].")"]);



        $rec = DianxingApi::delDevice($deviceid);


        if(isset($rec["StatusCode"]) && $rec["StatusCode"] != 204)
            return $response->withStatus(400)->withData(["error"=>"4","errorMsg"=>"电信平台删除设备失败(".$data["deviceId"].")"]);
        //删除设备
        try {
            Device::where("deviceId", $data["deviceId"])->delete();
        } catch (ReflectionException $e) {
            return $response->withStatus(400)->withData(["error"=>"5","errorMsg"=>$e->getMessage()]);
        } catch (ContainerException $e) {
            return $response->withStatus(400)->withData(["error"=>"5","errorMsg"=>$e->getMessage()]);
        } catch (DbException $e) {
            return $response->withStatus(400)->withData(["error"=>"5","errorMsg"=>$e->getMessage()]);
        }

        return $response->withData(["deviceId"=>$data["deviceId"],"Msg"=>"已删除"]);
    }
    /**
     * @RequestMapping("/v1/addDevice")
     * @throws Exception
     * @throws SwoftException
     * @throws DbException
     */
    public function addDevice(): Response
    {

        $request = Context()->getRequest();
        $response = Context()->getResponse();

        $mentod = $request->getMethod();

        $headers = $request->getHeaders();



        if($mentod == "POST")
            $data = $request->post();
        else {
            Log::error("Error!");
            return $response->withStatus(404);

        }



        if(!isset($data["deviceId"]))
            return $response->withStatus(400)->withData(["error"=>"1","errorMsg"=>"没有设置deviceId"]);
        if(!isset($data["productId"]))
            return $response->withStatus(400)->withData(["error"=>"2","errorMsg"=>"没有设置productId"]);
        if(!isset($data["model"]))
            return $response->withStatus(400)->withData(["error"=>"3","errorMsg"=>"没有设置model"]);
        if(!isset($data["imei"]))
            return $response->withStatus(400)->withData(["error"=>"4","errorMsg"=>"没有设置imei"]);
        if(!isset($data["isSecure"]) || !in_array($data["isSecure"],["true","false"]))
            return $response->withStatus(400)->withData(["error"=>"5","errorMsg"=>"没有设置isSecure或设置错误bool型"]);
        if(Context()->get("user") == null)
            return $response->withStatus(500)->withData(["errorMsg"=>"服务去错误"]);

        if(Product::where("productId",$data["productId"])->get()->count() <= 0)
            return $response->withStatus(400)->withData(["error"=>"6","errorMsg"=>"没有这个产品id(".$data["productId"].")"]);
        if(Device::where("deviceId",$data["deviceId"])->get()->count() > 0)
            return $response->withStatus(400)->withData(["error"=>"7","errorMsg"=>"设备id已存在(".$data["deviceId"].")"]);
        if(Device::where("imei",$data["imei"])->get()->count() > 0)
            return $response->withStatus(400)->withData(["error"=>"8","errorMsg"=>"imei已存在(".$data["imei"].")"]);




        $rec = DianxingApi::addDevice($data["imei"],$data["isSecure"]);

        if(isset($rec["error_code"]) && $rec["error_code"] == "100416")
            return $response->withStatus(400)->withData(["error"=>"9","errorMsg"=>"电信平台设备已绑定(".$data["imei"].")"]);
        if(isset($rec["error_code"]))
            return $response->withStatus(400)->withData(["error"=>"10","errorMsg"=>"电信平台其他错误(".$rec["error_code"].":".$rec["error_desc"].")"]);
        if(!isset($rec["deviceId"]) || !isset($rec["psk"]))
            return $response->withStatus(400)->withData(["error"=>"11","errorMsg"=>"电信平台错误(还回错误)"]);


        $r = false;
        try {
            $userid = User::where("UserName",Context()->get("user") )->get()[0]["userid"];
            $device = Device::new();
            $device->setDeviceId($data["deviceId"]);
            $device->setUserid($userid);
            $device->setProductId($data["productId"]);
            $device->setModel($data["model"]);
            $device->setImei($data["imei"]);
            $device->setIsSecure($data["isSecure"]);
            $key = $this->generate_str();
            $device->setKey($key);
            $device->setPsk($rec["psk"]);
            $device->setNb_deviceId($rec["deviceId"]);

            $r = $device->save();
        } catch (ReflectionException $e) {
            return $response->withStatus(400)->withData(["error"=>"12","errorMsg"=>$e->getMessage()]);
        } catch (ContainerException $e) {
            return $response->withStatus(400)->withData(["error"=>"12","errorMsg"=>$e->getMessage()]);
        } catch (DbException $e) {
            return $response->withStatus(400)->withData(["error"=>"12","errorMsg"=>$e->getMessage()]);
        }
        if(!$r)
            return $response->withStatus(400)->withData(["error"=>"12","errorMsg"=>"服务器数据库插入错误"]);

        $responseData = array("deviceId"=>$data["deviceId"],"key"=>$key);
        if($data["isSecure"] == "true")
        {
            $responseData["psk"] = $rec["psk"];
        }
        $responseData["time"] = $device->getCreatedDate();

        return $response->withData($responseData);


    }
    /**
     * @RequestMapping("/v1/deviceCommands")
     * @throws Exception
     * @throws SwoftException
     */
    public function deviceCommands(): Response
    {


        $request = Context()->getRequest();
        $response = Context()->getResponse();

        $mentod = $request->getMethod();

        $headers = $request->getHeaders();



        if($mentod == "POST")
            $data = $request->post();
        else {
            Log::error("Error!");
            return $response->withStatus(404);

        }
        if(Context()->get("user") == null)
            return $response->withStatus(500)->withData(["errorMsg"=>"服务去错误"]);

        if(!isset($data["deviceId"]))
            return $response->withStatus(404)->withData(["error"=>"1","errorMsg"=>"没有设置deviceId"]);
        if(!isset($data["cmd"]))
            return $response->withStatus(404)->withData(["error"=>"2","errorMsg"=>"没有设置cmd"]);
        try{
            $dbRec = Device::where("deviceId",$data["deviceId"])->select("Nb_deviceId");
            if($dbRec->count() > 0)
            {
                if($dbRec->get()[0]["Nb_deviceId"] != null ||$dbRec->get()[0]["Nb_deviceId"] != "" )
                {
                    $rec = DianxingApi::deviceCommands($dbRec->get()[0]["Nb_deviceId"],$data["cmd"],"http://swoft.sszlbg.cn/v1/deviceCommandsReply");
                    if(!isset($rec["commandId"]))
                    {
                        return $response->withStatus(404)->withData(["error"=>"5","errorMsg"=>"发送失败"]);
                    }
                    DeviceCmd::insert(["deviceId"=>$data["deviceId"],"cmd"=>json_encode($data["cmd"]),"NB_cmdId"=>$rec["commandId"],"sendDate"=>date("Y-m-d H:i:s")]);


                    return $response->withData(["user"=>Context()->get("user"),"deviceId"=>$data["deviceId"],"cmd"=>$data["cmd"],"cmdid"=>DeviceCmd::where("NB_cmdId",$rec["commandId"])->get()[0]["id"],"time"=>time()]);
                }
                else
                {

                    return $response->withStatus(404)->withData(["error"=>"4","errorMsg"=>"这个设备没有电信平台设备ID"]);
                }
            }
            else
            {
                return $response->withStatus(404)->withData(["error"=>"3","errorMsg"=>"没有这个设备"]);
            }
        } catch (ReflectionException $e) {
            return $response->withStatus(400)->withData(["error"=>"12","errorMsg"=>$e->getMessage()]);
        } catch (ContainerException $e) {
            return $response->withStatus(400)->withData(["error"=>"12","errorMsg"=>$e->getMessage()]);
        } catch (DbException $e) {
            return $response->withStatus(400)->withData(["error"=>"12","errorMsg"=>$e->getMessage()]);
        }


    }


    /**
     * 写日志
     * @param $data
     * @throws DbException
     */
    private function log_w($data)
    {
        $Log = LogIn::new();
        $Log->setDate(date("Y-m-d H:i:s"));
        $Log->setLog((string)$data);
        try {
            $Log->save();
        } catch (ReflectionException $e) {
            Log::error($e->getMessage());
        } catch (ContainerException $e) {
            Log::error($e->getMessage());
        } catch (DbException $e) {
            Log::error($e->getMessage());
        }
    }


    /**
     * 还回随机字符串
     * @param int $length
     * @return string
     */
    function generate_str( $length = 8 ) {

        // 密码字符集，可任意添加你需要的字符
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $password = "";
        for ( $i = 0; $i < $length; $i++ )
        {
            // 这里提供两种字符获取方式
            // 第一种是使用 substr 截取$chars中的任意一位字符；
            // 第二种是取字符数组 $chars 的任意元素
            // $password .= substr($chars, mt_rand(0, strlen($chars) – 1), 1)
            $password .= $chars[ mt_rand(0, strlen($chars) - 1) ];

        }

        return $password;

    }
}
